package com.imooc.springcloud;

import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @describte:测试
 * @program:spring-cloud
 * @author:zhengdp
 * @create:2021-09-28 14:53:04
 **/
@RestController
@Slf4j
public class Controller {

    // 2.0 ：限流组件 允许每秒钟发放两个通行证
    RateLimiter limiter = RateLimiter.create(2.0);

    /**
     * 非阻塞限流
     * @param count 当前请求需要消耗的令牌 (要获取的令牌数量）
     * @return
     */
    @GetMapping("/tryAcquire")
    public String tryAcquire(Integer count){
        if(limiter.tryAcquire(count)){
            log.info("success,rate is {}",limiter.getRate());
            return "success";
        }else{
            // 获取令牌失败
            log.info("fail, rate is {}",limiter.getRate());
            return "fail";
        }
    }


    /**
     * 限定时间的非阻塞限流
     * 当请求申请不到令牌时，会等待timeout时间
     * fast-fail机制
     * @param count 要申请的令牌数
     * @param timeout 限定时间
     * @return
     */
    @GetMapping("/tryAcquireWithTimeout")
    public String tryAcquireWithTimeout(Integer count,Integer timeout){
        if(limiter.tryAcquire(count,timeout, TimeUnit.SECONDS)){
            log.info("success,rate is {}",limiter.getRate());
            return "success";
        }else{
            // 获取令牌失败
            log.info("fail, rate is {}",limiter.getRate());
            return "fail";
        }
    }

    /**
     * 同步阻塞限流
     * 令牌不足，请求会阻塞等待令牌满足
     * @param count
     * @return
     */
    @GetMapping("/acquire")
    public String acquire(Integer count){
        double acquire = limiter.acquire(count);
        log.info("success, rate is {}",limiter.getRate());
        return "success";
    }

    /*
    * 非阻塞限流和阻塞限流
    * 但这个并不是真正意义上的分布式限流==>只是在当前服务器上起作用。
    * 用在对单机资源敏感的访问请求上。
    * 单机限流并不适用于需要访问分布式环境中某些中间件组件的方法。
    * 比如要访问Redis，访问数据库。数据库是要作用于整个集群的。
    * */

    /**
     * Nginx专用
     * 1. 修改host文件 -> www.imooc-training.com = localhost 127.0.0.1
     * 2. 修改Nginx -->将步骤1的域名添加到路由规则当中  nginx.conf文件
     * 3. 添加配置项
     * @return
     */
    @GetMapping("/nginx")
    public String nginx(){
        log.info("Nginx success");
        return "success";
    }

    /**
     * 测试Nginx的基于连接数的限流规则
     * @param secs 休眠时间
     * @return
     */
    @GetMapping("/nginx-conn")
    public String nginxConn(@RequestParam(defaultValue = "0") int secs){
        try{
            Thread.sleep(1000*secs);
        }catch (Exception e){

        }
        return "success";
    }
}
